﻿using FirstFloor.ModernUI.Windows.Controls;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using Vtron.LEDCorrective.Core;
using Vtron.LEDCorrective.Domain.LEDSender;
using Vtron.LEDCorrective.EDSDKWrapper;

namespace Vtron.LEDCorrective.Pages
{
    /// <summary>
    /// PartitionCorrective.xaml 的交互逻辑
    /// </summary>
    public partial class PartitionCorrective : UserControl
    {
        public PartitionCorrective()
        {
            InitializeComponent();
        }

        private bool isContinue = false;
        private CorrectiveEngine correctiveEngine = CorrectiveEngine.Instance;
        private int partitionNum = 0;

        public int PartitionNum
        {
            get { return partitionNum; }
            set
            {
                if (partitionNum != value)
                {
                    partitionNum = value;

                    int i = partitionNum % correctiveEngine.SeparateColumn;
                    if (i == 0)
                    {
                        i = correctiveEngine.SeparateColumn;
                    }
                    int j = (int)Math.Ceiling((float)partitionNum / correctiveEngine.SeparateColumn);

                    WCF.MessageClient client = new WCF.MessageClient();
                    client.Show(System.Drawing.Color.White, correctiveEngine.PartitionColumn * (i - 1), correctiveEngine.PartitionRow * (j - 1), correctiveEngine.PartitionColumn, correctiveEngine.PartitionRow, 1, 1, 1);

                    Dispatcher.BeginInvoke(new Action(() =>
                    {
                        red_txt.Visibility = Visibility.Collapsed;
                        green_txt.Visibility = Visibility.Collapsed;
                        blue_txt.Visibility = Visibility.Collapsed;
                        build_txt.Visibility = Visibility.Collapsed;
                        upload_txt.Visibility = Visibility.Collapsed;
                        hw_txt.Visibility = Visibility.Collapsed;
                        partitionNum_txt.Text = partitionNum.ToString();
                    }));
                }
            }
        }
        private bool auto = true;

        private void corrective_btn_Click(object sender, RoutedEventArgs e)
        {
            corrective_btn.IsEnabled = false;
            continue_btn.IsEnabled = false;
            partitionTopological_btn.IsEnabled = false;

            string directoryPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Vtron\\LEDCorrective";
            string path = String.Format("{0}\\{1}", directoryPath, "RemotePhoto");

            if (Directory.Exists(path))
            {
                Directory.Delete(path, true);
                Directory.CreateDirectory(path);
            }

            if (correctiveEngine.PartitionColumn == 0 || correctiveEngine.PartitionRow == 0)
            {
                ModernDialog.ShowMessage("请先分区，再进行分区校正！", "提示", MessageBoxButton.OK);
                corrective_btn.IsEnabled = true;
                partitionTopological_btn.IsEnabled = true;
                return;
            }

            if (partitionNum == 0)
            {
                ModernDialog.ShowMessage("请先选择分区，再进行分区校正！", "提示", MessageBoxButton.OK);
                corrective_btn.IsEnabled = true;
                partitionTopological_btn.IsEnabled = true;
                return;
            }

            LEDCollection ledCollection = correctiveEngine.LedCollections[partitionNum - 1];

            //correctiveEngine.CurrentSenderId = correctiveEngine.Scp_wall.modpg[0].senderId.id;
            //correctiveEngine.CurrentModeGroupId = correctiveEngine.Scp_wall.modpg[0].modgpId;

            //bool result = SetScan();
            //if (!result)
            //{
            //    corrective_btn.IsEnabled = true;
            //    return;
            //}

            SetAdjustDots(false);

            int i = partitionNum % correctiveEngine.SeparateColumn;
            if (i == 0)
            {
                i = correctiveEngine.SeparateColumn;
            }
            int j = (int)Math.Ceiling((float)partitionNum / correctiveEngine.SeparateColumn);

            new Action(() =>
            {
                Dispatcher.BeginInvoke(new Action(() =>
                {
                    red_txt.Visibility = Visibility.Collapsed;
                    green_txt.Visibility = Visibility.Collapsed;
                    blue_txt.Visibility = Visibility.Collapsed;
                    build_txt.Visibility = Visibility.Collapsed;
                    upload_txt.Visibility = Visibility.Collapsed;
                    hw_txt.Visibility = Visibility.Collapsed;
                    red_ProBar.Visibility = Visibility.Visible;
                    partitionNum_txt.Text = partitionNum.ToString();
                }));

                correctiveEngine.isSetRadiusSize = false;
                correctiveEngine.BlockNum = 1;
                RedDataCollectionFlow(ledCollection, correctiveEngine.PartitionColumn * (i - 1), correctiveEngine.PartitionRow * (j - 1));
            }).BeginInvoke(null, null);
        }

        private void RedDataCollectionFlow(LEDCollection ledCollection, int left, int top)
        {
            DataCollection(System.Drawing.Color.Red, ledCollection, left, top);

            new Action(() =>
            {
                while (true)
                {
                    if (isContinue)
                    {
                        isContinue = false;
                        break;
                    }
                    else
                    {
                        Thread.Sleep(500);
                    }
                }

                Dispatcher.BeginInvoke(new Action(() =>
                {
                    red_ProBar.Visibility = Visibility.Collapsed;
                    red_txt.Visibility = Visibility.Visible;
                    green_ProBar.Visibility = Visibility.Visible;
                }));

                correctiveEngine.BlockNum = 1;
                GreenDataCollectionFlow(ledCollection, left, top);

            }).BeginInvoke(null, null);
        }

        private void GreenDataCollectionFlow(LEDCollection ledCollection, int left, int top)
        {
            DataCollection(System.Drawing.Color.Green, ledCollection, left, top);

            new Action(() =>
            {
                while (true)
                {
                    if (isContinue)
                    {
                        isContinue = false;
                        break;
                    }
                    else
                    {
                        Thread.Sleep(500);
                    }
                }

                Dispatcher.BeginInvoke(new Action(() =>
                {
                    green_ProBar.Visibility = Visibility.Collapsed;
                    green_txt.Visibility = Visibility.Visible;
                    blue_ProBar.Visibility = Visibility.Visible;
                }));

                correctiveEngine.BlockNum = 1;
                BlueDataCollectionFlow(ledCollection, left, top);

            }).BeginInvoke(null, null);
        }

        private void BlueDataCollectionFlow(LEDCollection ledCollection, int left, int top)
        {
            DataCollection(System.Drawing.Color.Blue, ledCollection, left, top);

            new Action(() =>
            {
                while (true)
                {
                    if (isContinue)
                    {
                        isContinue = false;
                        break;
                    }
                    else
                    {
                        Thread.Sleep(500);
                    }
                }

                Dispatcher.BeginInvoke(new Action(() =>
                {
                    blue_ProBar.Visibility = Visibility.Collapsed;
                    blue_txt.Visibility = Visibility.Visible;
                    build_ProBar.Visibility = Visibility.Visible;
                }));

                WCF.MessageClient client = new WCF.MessageClient();
                client.Show(System.Drawing.Color.White, left, top, correctiveEngine.PartitionColumn, correctiveEngine.PartitionRow, 1, 1, 1);

                try
                {
                    correctiveEngine.CountOffset(partitionNum);
                }
                catch (Exception ex)
                {
                    Dispatcher.BeginInvoke(new Action(() =>
                    {
                        string msg = String.Empty;
                        msg = String.Format("校正时发生错误，错误信息：{0}", ex.Message);
                        if (auto)
                        {
                            msg_TextBlock.AppendText("\r\n" + msg);
                        }
                        else
                        {
                            ModernDialog.ShowMessage(msg, "错误", MessageBoxButton.OK);
                        }

                        corrective_btn.IsEnabled = true;
                        partitionTopological_btn.IsEnabled = true;
                    }));

                    return;
                }

                bool isDone = false;
                while (!isDone)
                {
                    if (correctiveEngine.LedCollections[partitionNum - 1].IsDone)
                    {
                        Dispatcher.BeginInvoke(new Action(() =>
                        {
                            build_ProBar.Visibility = Visibility.Collapsed;
                            build_txt.Visibility = Visibility.Visible;
                            upload_ProBar.Visibility = Visibility.Visible;
                        }));

                        SetAdjustDots(true);

                        correctiveEngine.SetModGPAdjust();

                        Dispatcher.BeginInvoke(new Action(() =>
                        {
                            upload_ProBar.Visibility = Visibility.Collapsed;
                            upload_txt.Visibility = Visibility.Visible;
                            hw_ProBar.Visibility = Visibility.Visible;
                        }));

                        //correctiveEngine.SetHwmodGPDots();

                        Dispatcher.BeginInvoke(new Action(() =>
                        {
                            hw_ProBar.Visibility = Visibility.Collapsed;
                            hw_txt.Visibility = Visibility.Visible;
                        }));

                        isDone = true;
                        Dispatcher.BeginInvoke(new Action(() =>
                        {
                            corrective_btn.IsEnabled = true;
                            partitionTopological_btn.IsEnabled = true;
                        }));
                    }
                    else
                    {
                        Thread.Sleep(1000);
                    }
                }

            }).BeginInvoke(null, null);
        }

        private void DataCollection(System.Drawing.Color color, LEDCollection ledCollection, int left, int top)
        {
            WCF.MessageClient client = new WCF.MessageClient();
            client.Show(color, left, top, correctiveEngine.PartitionColumn, correctiveEngine.PartitionRow, correctiveEngine.BlockColumn, correctiveEngine.BlockRow, correctiveEngine.BlockNum);

            Dispatcher.BeginInvoke(new Action(() =>
            {
                try
                {
                    EDSDKHandler.Instance.TakePhoto(CameraValues.TV("1/4"), CameraValues.ISO("ISO 100"));
                }
                catch (Exception ex)
                {
                    string msg = String.Format("拍照时时发生错误，错误信息：{0}", ex.Message);
                    ModernDialog.ShowMessage(msg, "错误", MessageBoxButton.OK);

                    return;
                }
            }));
            correctiveEngine.PicId++;
            new Action(() =>
            {
                try
                {
                    string destPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Vtron\\LEDCorrective";
                    string sourcePath = String.Format("{0}\\{1}", destPath, "RemotePhoto");
                    string sourceFileName = String.Format("{0}\\IMG_{1}.CR2", sourcePath, correctiveEngine.PicId.ToString().PadLeft(4, '0'));
                    string destFileName = String.Format("{0}\\{1}_{2}_{3}_{4}.tiff", destPath, correctiveEngine.Id, partitionNum, correctiveEngine.BlockNum, color.Name);

                    while (!File.Exists(sourceFileName) && IsFileInUse(sourceFileName))
                    {
                        Thread.Sleep(500);
                    }

                    string command = String.Format("{0}\\dcrawMS.exe -o 0 -4 -T {1}", destPath, sourceFileName);
                    Process p = new Process();
                    p.StartInfo.FileName = "cmd.exe";
                    p.StartInfo.Arguments = "/c" + command;
                    p.StartInfo.UseShellExecute = false;
                    p.StartInfo.RedirectStandardInput = true;
                    p.StartInfo.RedirectStandardOutput = true;
                    p.StartInfo.RedirectStandardError = true;
                    p.StartInfo.CreateNoWindow = true;
                    p.Start();
                    p.StandardOutput.ReadToEnd();
                    p.WaitForExit();
                    p.Close();
                    if (File.Exists(destFileName))
                    {
                        File.Delete(destFileName);
                    }

                    string sourceTiffFileName = String.Format("{0}\\IMG_{1}.tiff", sourcePath, correctiveEngine.PicId.ToString().PadLeft(4, '0'));
                    int k = 0;
                    while (!File.Exists(sourceTiffFileName))
                    {
                        k++;

                        if (k > 4)
                        {
                            k = 0;
                            p = new Process();
                            p.StartInfo.FileName = "cmd.exe";
                            p.StartInfo.Arguments = "/c" + command;
                            p.StartInfo.UseShellExecute = false;
                            p.StartInfo.RedirectStandardInput = true;
                            p.StartInfo.RedirectStandardOutput = true;
                            p.StartInfo.RedirectStandardError = true;
                            p.StartInfo.CreateNoWindow = true;
                            p.Start();
                            p.StandardOutput.ReadToEnd();
                            p.WaitForExit();
                            p.Close();
                        }
                        else
                        {
                            Thread.Sleep(500);
                        }
                    }

                    File.Move(sourceTiffFileName, destFileName);

                    while (!File.Exists(destFileName) && IsFileInUse(destFileName))
                    {
                        Thread.Sleep(100);
                    }

                    int count = correctiveEngine.PartitionDataAnalysis(partitionNum, ledCollection, color);

                    string msg = String.Empty;
                    msg = String.Format("\r\n{0}采集到{1}个LED点", color.Name, count);
                    if (correctiveEngine.badLED.Count() > 0)
                    {
                        msg += String.Format(",其中有{0}个坏点或暗点无法采集，\r\n坏点或暗点位置如下：", correctiveEngine.badLED.Count());

                        for (int i = 0; i < correctiveEngine.badLED.Count(); i++)
                        {
                            msg += String.Format("\r\n行：{0},列：{1}", correctiveEngine.badLED[i].Row, correctiveEngine.badLED[i].Column);
                        }
                    }
                    else
                    {
                        msg += ",没有坏点或暗点";
                    }

                    Dispatcher.BeginInvoke(new Action(() =>
                    {
                        msg_TextBlock.AppendText(msg);
                    }));

                    if (correctiveEngine.BlockNum == correctiveEngine.BlockColumn * correctiveEngine.BlockRow)
                    {
                        if (auto)
                        {
                            isContinue = true;
                        }
                        else
                        {
                            Dispatcher.BeginInvoke(new Action(() =>
                            {
                                continue_btn.IsEnabled = true;
                            }));
                        }

                        return;
                    }
                    else
                    {
                        correctiveEngine.BlockNum++;
                        DataCollection(color, ledCollection, left, top);
                    }
                }
                catch (Exception ex)
                {
                    Dispatcher.BeginInvoke(new Action(() =>
                    {
                        string msg = String.Empty;
                        msg = String.Format("数据采集时时发生错误，错误信息：{0}", ex.Message);
                        if (auto)
                        {
                            msg_TextBlock.AppendText("\r\n" + msg);
                        }
                        else
                        {
                            ModernDialog.ShowMessage(msg, "错误", MessageBoxButton.OK);
                        }

                        DataCollection(color, ledCollection, left, top);
                    }));
                }
            }).BeginInvoke(null, null);
        }

        private void continue_btn_Click(object sender, RoutedEventArgs e)
        {
            isContinue = true;
            continue_btn.IsEnabled = false;
        }

        private bool SetScan()
        {
            int wallWidth = correctiveEngine.WallWidth;
            int wallHeight = correctiveEngine.WallHeight;

            SCP_SCAN_T scan = correctiveEngine.GetScan();
            if (wallWidth < SystemParameters.PrimaryScreenWidth && wallHeight < SystemParameters.PrimaryScreenHeight)
            {
                scan.clipBeginX = 0;
                scan.clipBeginY = 0;
                scan.clipEndX = (ushort)(scan.clipBeginX + wallWidth);
                scan.clipEndY = (ushort)(scan.clipBeginY + wallHeight);
            }
            else
            {
                ModernDialog.ShowMessage("暂未支持,墙体分辨率比PC分辨率高", "错误", MessageBoxButton.OK);
                return false;
            }

            SCP_STATUS_T result = correctiveEngine.SetScan(scan);
            return true;
        }

        private void partitionTopological_btn_Click(object sender, RoutedEventArgs e)
        {
            if (correctiveEngine.PartitionColumn == 0 || correctiveEngine.PartitionRow == 0)
            {
                ModernDialog.ShowMessage("分区后才能查看拓扑图！", "提示", MessageBoxButton.OK);
                return;
            }

            TopologicalWindow window = new TopologicalWindow(this);
            window.Show();
        }

        private void auto_CheckBox_Click(object sender, RoutedEventArgs e)
        {
            auto = (bool)auto_CheckBox.IsChecked;
        }

        /// <summary>
        /// 判断文件是否被占用
        /// </summary>
        /// <param name="fileName">文件路径</param>
        /// <returns>返回值</returns>
        private bool IsFileInUse(string fileName)
        {
            bool inUse = true;

            FileStream fs = null;
            try
            {
                fs = new FileStream(fileName, FileMode.Open, FileAccess.Read,

                FileShare.None);

                inUse = false;
            }
            catch
            {

            }
            finally
            {
                if (fs != null)

                    fs.Close();
            }

            //True表示正在使用,False表示没有使用
            return inUse;
        }

        private void SetAdjustDots(bool b)
        {
            correctiveEngine.SetAdjustDots(b);

            if (correctiveEngine.GetAdjustDots() == !b)
            {
                Thread.Sleep(100);
                SetAdjustDots(b);
            }
        }
    }
}